

const fs = require("fs");
const stream = require("stream");
const path = require("path");
const util = require("util");
const randomstring = require("randomstring");
const mongo = require("./mongo");
const dbg = require("debug")("[index.js]"); dbg.enabled = true;
const Collection_Name = "Alibaba" + parseInt(Math.random() * 10000);
dbg(Collection_Name);
let phase = 0;
let buf = "";
let tmpImageType = "";

let store = {
    boundary: "",
    messages: [],
    html: [],
    pic: {
        type: "xxx",
        cid: "xxxx",
        content: "xxx"
    }
};

(async () => {
    let client = await mongo.connect();
    let collection = client.db('qq-mht-parser').collection(Collection_Name);
    let fileReadStream = fs.createReadStream(
        path.join(__dirname, "./Alibaba.mht"),
        {
            encoding: "utf8",
            highWaterMark: 1 * 1024
        }
    );
    /**@param {String} line */
    let line_process_func = async function (line) {
        dbg(`phase is ${phase}`, `line is ${line}}`);
        return new Promise(async (resolve) => {
            if (line.length == 0) {
                resolve("length==0");
            }
            if (phase == 0) {
                if (line.startsWith("\tboundary=")) {
                    let boundary = line.replace("\tboundary=", "").split("\"")[1];
                    store.boundary = boundary;
                    let inserted = await collection.insert({ type: "boundary", value: boundary });
                    phase = 1;
                    resolve({ phase_now: phase, inserted });
                } else {
                    resolve("null");
                }
            } else if (phase == 1) {
                if (line.includes(store.boundary)) {
                    phase = 2;
                    resolve({ phase_now: phase });
                } else {
                    resolve(null);
                }
            } else if (phase == 2) {
                if (line.startsWith("Content-Type")) {
                    if (line.includes("image/")) {
                        tmpImageType = line.replace("Content-Type:", "");
                        phase = 22;
                    } else {
                        //html
                        phase = 21
                    }
                    resolve({ phase_now: phase });
                } else {
                    resolve("null");
                }

            } else if (phase == 21) {
                //html
                if (line.startsWith("<") && line.endsWith(">")) {
                    let matched = line.match(/<tr><td.*<\/td><\/tr>/g);
                    if (line.includes(`</html>`)) {
                        phase = 1;
                    }
                    if (Array.isArray(matched)) {
                        //这里好像可能会丢失一些顺序
                        let all_inserted = await Promise.all(matched.map(m => new Promise(async r => {
                            store.html.push(m);
                            let inserted = await collection.insert({
                                type: "html",
                                value: m
                            }).catch(err => {
                                r(err);
                            });
                            r(inserted);
                        })));
                        resolve({ phase_now: phase, all_inserted });

                    }
                    resolve({ phase_now: phase });
                } else {
                    resolve("null");
                }
            } else if (phase == 22) {
                //image
                let image_str_debug = randomstring.generate(4);
                if (line.startsWith("Content")) {
                    if (line.startsWith("Content-Location")) {
                        let tempPic = {
                            cid: line.replace("Content-Location:{", "").replace("}.dat", ""),
                            type: tmpImageType,
                            content: ""
                        }

                        tmpImageType = "";
                        let inserted = await collection.insert({
                            type: "image",
                            cid: tempPic.cid,
                            image_type: tempPic.type,
                            content: tempPic.content
                        });
                        store.pic.cid = tempPic.cid;
                        store.pic.type = tempPic.type
                        store.pic.content = tempPic.content;
                        dbg(`<${image_str_debug}>|store-cid:${store.pic.cid}|insert-cid:${inserted.ops[0].cid}`)
                        resolve({ phase_now: phase, inserted });
                    } else {
                        resolve("null");
                    }
                } else {
                    if (line.includes(store.boundary)) {
                        phase = 2;
                        dbg(`<${image_str_debug}>|store-cid:${store.pic.cid}|next-phase-is-2`);
                        resolve({ phase_now: phase });
                    } else {
                        store.pic.content += `${line}\n`;
                        let image_doc = await collection.findOne({
                            cid: store.pic.cid
                        });
                        dbg(`<${image_str_debug}>|store-cid:${store.pic.cid}|find-cid:${image_doc['cid']}`);
                        let content = image_doc['content'];
                        content += `${line}\n`;
                        let updated = await collection.
                            findOneAndUpdate(
                                {
                                    cid: store.pic.cid
                                },
                                {
                                    cid: image_doc['cid'],
                                    content: content,
                                    image_type: image_doc['image_type'],
                                    type: image_doc['type']
                                })
                            .catch(err => {
                                resolve(err);
                                // debugger
                            })
                        dbg(`<${image_str_debug}>|store-cid:${store.pic.cid}|updated-cid:${updated.value['cid']}`);
                        resolve({ updated });
                    }
                }
            }
        })
    }
    fileReadStream.on("data", async (chunk) => {
        let chunk_arr = String(buf + chunk).split("\n");
        buf = "";
        fileReadStream.pause();

        for (let i = 0; i < chunk_arr.length;) {
            if (i == chunk_arr.length - 1) {
                buf = chunk_arr[i];
                break;
            }
            let line = chunk_arr[i];
            let processed = await line_process_func(line);
            if (typeof process == "object") {
                // dbg(`[processed-${i}`);
                dbg("%j", processed)
            } else {
                dbg(`[processed-${i} ${processed}]`)
            }

            i++
        }
        fileReadStream.resume();
        " debugger"
    })

    fileReadStream.on("close", () => {
        store
    })

})();

